/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { TypeNode, SyntaxKind, TupleTypeNode } from 'ts-morph';
import { PropertyKind, TypeStructure, SerializerMetadata, TypeDependency } from '../Types';
import { ConversionDirection, ITypeHandler, TypeContext } from './ITypeHandler';
import { BaseTypeHandler } from './BaseTypeHandler';
import { CustomError, ErrorCodes } from '../utils/CustomError';
import { Logger } from '../logger/Logger';

class TupleHandler extends BaseTypeHandler implements ITypeHandler {
  readonly name = 'TupleHandler';
  readonly kind = PropertyKind.TUPLE;
  readonly priority = 95;

  // ==================== 阶段1: 类型识别 ====================

  matches(typeNode: TypeNode): boolean {
    return typeNode.getKind() === SyntaxKind.TupleType;
  }

  // ==================== 阶段2: 类型解析 ====================

  parse(typeNode: TypeNode, context: TypeContext): TypeStructure {
    const tupleType = typeNode as TupleTypeNode;
    const elementTypes = tupleType.getElements();

    // 解析所有元素类型
    const elements: TypeStructure[] = [];
    const allDependencies: TypeDependency[] = [];
    let maxDepth = 0;

    for (const elementType of elementTypes) {
      const { TypeHandlerRegistry } = require('./TypeHandlerRegistry');
      const elementStructure = TypeHandlerRegistry.getInstance().parseType(elementType, {
        ...context,
        depth: context.depth + 1
      });

      Logger.info(`tuple element type: ${elementType.getText()}, ${elementStructure.kind}`);
      elements.push(elementStructure);
      allDependencies.push(...elementStructure.dependencies);
      maxDepth = Math.max(maxDepth, elementStructure.depth);
    }

    return {
      kind: this.kind,
      depth: maxDepth + 1,
      sourceText: typeNode.getText(),
      args: elements,
      dependencies: allDependencies
    };
  }

  // ==================== 阶段3: 序列化器配置 ====================

  getSerializerMetadata(structure: TypeStructure, withParam?: string): SerializerMetadata {
    const serializerName = this.getSerializerName();
    const defaultInstantiation = this.generateInstantiation(structure);

    return {
      name: serializerName,
      typeDeclaration: this.generateTypeDeclaration(structure),
      instantiationTemplate: this.applyWithParam(withParam, defaultInstantiation, structure),
      encodeMethod: 'encodeSerializableElement',
      decodeMethod: 'deserialize',
      decoderType: `${structure.sourceText} | undefined`,
      needsTypeAssertion: false
    };
  }

  // ==================== 阶段4: 代码生成 ====================

  generateInstantiation(structure: TypeStructure): string {

    const serializerName = this.getSerializerName();

    // 为每个元组元素生成序列化器
    const elementSerializers = structure.args.map(element => {
      const { TypeHandlerRegistry } = require('./TypeHandlerRegistry');
      const handler = TypeHandlerRegistry.getInstance().getHandlerForKind(element.kind);
      return handler.generateInstantiation(element);
    });

    return `new ${serializerName}([${elementSerializers.join(', ')}])`;
  }

  generateTypeDeclaration(structure: TypeStructure): string {
    const serializerName = this.getSerializerName();
    return `${serializerName}<${structure.sourceText}>`;
  }

  generateTypeKey(structure: TypeStructure): string {

    const elementKeys = structure.args.map(element => {
      const { TypeHandlerRegistry } = require('./TypeHandlerRegistry');
      const handler = TypeHandlerRegistry.getInstance().getHandlerForKind(element.kind);
      return handler.generateTypeKey(element);
    });

    return `[${elementKeys.join(', ')}]`;
  }

  protected getSerializerName(): string {
    return 'TupleSerializer';
  }

  // ==================== Sendable转换 ====================

  generateSendableTypeDeclaration(structure: TypeStructure): string {

    const registry = require('./TypeHandlerRegistry').TypeHandlerRegistry.getInstance();
    const sendableElementTypes = structure.args.map(element => {
      const handler = registry.getHandlerForKind(element.kind);
      if (!handler) {
        throw new CustomError(`TupleHandler: no handler for element type: ${element.kind}`, ErrorCodes.HANDLER_NOT_FOUND);
      }
      return handler.generateSendableTypeDeclaration(element);
    });

    return `[${sendableElementTypes.join(', ')}]`;
  }

  generatePropertyConversion(structure: TypeStructure, sourceValue: string, direction: ConversionDirection): string {
    // 元组类型的转换无法在编译时确定具体类型，直接传递
    // 实际转换由运行时的具体类型决定
    return sourceValue;
  }
}

export function createTupleTypeHandlers(): ITypeHandler {
  return new TupleHandler();
}